package com.sharer.last.utils.comment;

import com.sharer.last.base.utils.StringUtil;
import com.sharer.last.config.properties.BlogProperties;
import com.sharer.last.constant.RedisKeyConstants;
import com.sharer.last.enums.CommentTypeEnum;
import com.sharer.last.model.po.CommentPO;
import com.sharer.last.service.*;
import com.sharer.last.utils.HashUtils;
import com.sharer.last.utils.MailUtils;
import com.sharer.last.utils.QQInfoUtils;
import com.sharer.last.utils.comment.channel.ChannelFactory;
import com.sharer.last.utils.comment.channel.CommentNotifyChannel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 评论工具类
 *
 * @ClassName CommentUtils
 * @Author wangjin
 * @Date 2023/5/5 20:47
 * @Description
 * @Version 1.0
 */
@Component
@DependsOn("springContextUtils")
public class CommentUtils {
    @Resource
    private BlogProperties blogProperties;

    @Resource
    private MailUtils mailUtils;

    @Resource
    private RedisService redisService;

    @Resource
    QQInfoUtils qqInfoUtils;

    private CommentNotifyChannel notifyChannel;

    @Value("${comment.notify.channel}")
    public void setNotifyChannel(String channelName) {
        this.notifyChannel = ChannelFactory.getChannel(channelName);
    }


    /**
     * 判断是否发送提醒
     * 6种情况：
     * 1.我以父评论提交：不用提醒
     * 2.我回复我自己：不用提醒
     * 3.我回复访客的评论：只提醒该访客
     * 4.访客以父评论提交：只提醒我自己
     * 5.访客回复我的评论：只提醒我自己
     * 6.访客回复访客的评论(即使是他自己先前的评论)：提醒我自己和他回复的评论
     *
     * @param comment          当前收到的评论
     * @param isVisitorComment 是否访客评论
     * @param parentComment    父评论
     */
    public void judgeSendNotify(CommentPO comment, boolean isVisitorComment, CommentPO parentComment) {
        if (parentComment != null && parentComment.getIsAdminComment() == 0 && parentComment.getIsNotice() == 1) {
            //我回复访客的评论，且对方接收提醒，邮件提醒对方(3)
            //访客回复访客的评论(即使是他自己先前的评论)，且对方接收提醒，邮件提醒对方(6)
            sendMailToParentComment(parentComment, comment);
        }
        if (isVisitorComment) {
            //访客以父评论提交，只提醒我自己(4)
            //访客回复我的评论，提醒我自己(5)
            //访客回复访客的评论，不管对方是否接收提醒，都要提醒我有新评论(6)
            notifyMyself(comment);
        }
    }

    /**
     * 发送邮件提醒回复对象
     *
     * @param parentComment 父评论
     * @param comment       当前收到的评论
     */
    private void sendMailToParentComment(CommentPO parentComment, CommentPO comment) {
        CommentTypeEnum     commentTypeEnum = CommentTypeEnum.getEnum(comment.getCommentType());
        Map<String, Object> map             = new HashMap<>(16);
        map.put("parentNickname", parentComment.getNickname());
        map.put("nickname", comment.getNickname());
        map.put("title", commentTypeEnum.getTitle());
        map.put("time", comment.getCreateTime());
        map.put("parentContent", parentComment.getContent());
        map.put("content", comment.getContent());
        map.put("url", blogProperties.getView() + commentTypeEnum.getPath());
        String toAccount = parentComment.getEmail();
        String subject   = "您在 " + blogProperties.getName() + " 的评论有了新回复";
        mailUtils.sendHtmlTemplateMail(map, toAccount, subject, "guest.html");
    }

    /**
     * 通过指定方式通知自己
     *
     * @param comment 当前收到的评论
     */
    private void notifyMyself(CommentPO comment) {
        notifyChannel.notifyMyself(comment);
    }

    /**
     * 对于昵称不是QQ号的评论，根据昵称Hash设置头像
     *
     * @param nickName 昵称
     */
    public String setCommentRandomAvatar(String nickName) {
        //设置随机头像
        //根据评论昵称取Hash，保证每一个昵称对应一个头像
        long nicknameHash = HashUtils.getMurmurHash32(nickName);
        //计算对应的头像
        long num = nicknameHash % 6 + 1;
        return "/img/comment-avatar/" + num + ".jpg";
    }

    /**
     * 设置QQ头像，复用已上传过的QQ头像，不再重复上传
     *
     * @param qq QQ号
     * @throws Exception 上传QQ头像时可能抛出的异常
     */
    public String setCommentQQAvatar(String qq) throws Exception {
        String uploadAvatarUrl = (String) redisService.hGet(RedisKeyConstants.QQ_AVATAR_URL_MAP, qq);
        if (StringUtil.isBlank(uploadAvatarUrl)) {
            uploadAvatarUrl = qqInfoUtils.getQQAvatarUrl(qq);
            redisService.hSet(RedisKeyConstants.QQ_AVATAR_URL_MAP, qq, uploadAvatarUrl);
        }
        return uploadAvatarUrl;
    }

    /**
     * URL合法性校验
     *
     * @param url url
     * @return 是否合法
     */
    private static boolean isValidUrl(String url) {
        return url.matches("^https?://([^!@#$%^&*?.\\s-]([^!@#$%^&*?.\\s]{0,63}[^!@#$%^&*?.\\s])?\\.)+[a-z]{2,6}/?");
    }
}
